Lambda から IAM 認証が有効な API Gateway にアクセスしてみた
はじめに
アノテーション株式会社の hato です。
API Gateway で IAM 認証を有効にすると、必要な権限(execute-api:Invoke
)をもった IAM 認証情報が含まれるリクエストのみにアクセスを限定することができます。
IAM 認証が有効な API Gatewayを作成する方法は AWS ナレッジセンターにて公開されていますが、実際に構築したことはなかったのと、お問い合わせ頂いた際に備えて画面キャプチャを取得するため、やってみました。
なお、今回はリクエストの送信元(クライアント)に Lambda 関数を使用しています。
やってみた
前提
API Gateway には次の固定値を返却する Mock エンドポイントをデプロイ済み(IAM 認証は無効な状態)
{ "statusCode": 200, "message": "Hello, world!" }
構成イメージ
手順
- IAM 認証の有効化
- Lambda 関数のコード作成
- Lambda 関数の作成
- テスト
1. IAM 認証の有効化
API Gateway コンソールの「リソース」ペインから、IAM 認証を有効にするメソッドを選択します。
「メソッドリクエスト」を選択します。
「認可」の鉛筆マークを選択します。
「AWS IAM」を選択してチェックマークを選択します。
「アクション」 -> 「API のデプロイ」を選択します。
「デプロイ」を選択します。
呼び出し URL は後ほどクライアントに設定するため、書き留めます。
2. Lambda 関数のコード作成
API Gateway に AWS の署名バージョン 4 で署名したリクエストを送信するサンプルコードを作成します。
署名バージョン 4 の署名には requests-aws4auth を使用しています。
作業用のディレクトリを作成します。
$ mkdir my-sourcecode-function $ cd my-sourcecode-function
エディタで次のサンプルコードを作成します。
※6行目は「呼び出し URL」に修正してください。
import boto3 import requests from requests_aws4auth import AWS4Auth def lambda_handler(event, context): url = "<API_GATEWAY_URL>" credentials = boto3.Session().get_credentials() region = 'ap-northeast-1' service = 'execute-api' auth = AWS4Auth( credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token, ) response = requests.get(url, auth=auth) return(response.json())
pip
で周辺モジュールをインストールして、ZIP圧縮します。
$ pip install --target ./package requests requests_aws4auth ...(中略)... Successfully installed certifi-2022.12.7 charset-normalizer-3.0.1 idna-3.4 requests-2.28.2 requests-aws4auth-1.1.2 six-1.16.0 urllib3-1.26.14 $ cd package $ zip -r ../my-deployment-package.zip . ...(中略)... adding: bin/ (stored 0%) adding: bin/normalizer (deflated 27%) $ cd .. $ zip -g my-deployment-package.zip lambda_function.py adding: lambda_function.py (deflated 47%)
3. Lambda 関数の作成
クライアントとなる Lambda 関数を作成します。
Lambda コンソールを開き、関数から「関数の作成」をクリックします。
次の値を指定して「関数の作成」を選択します。
- 関数名:任意の名前(例:
hato-client-lambda
) - ランタイム:Python 3.9
Lambda の作成後、API Gateway のアクセスに必要な権限を設定します。
「設定」タブの「アクセス権限」を選択します。
ロール名のリンクをクリックします。
「許可の追加」から「ポリシーのアタッチ」を選択します。
許可ポリシーから「AmazonAPIGatewayInvokeFullAccess」ポリシーを選択して、「ポリシーをアタッチ」をクリックします。
※すべての API Gateway の呼び出し権限が付与されるため、AWS 公式ドキュメントを参考に最小権限を付与することを推奨します。
IAM ロールが正常に更新されたことを確認します。
作成したサンプルコードを設定します。 「アップロード元」から「.zipファイル」を選択
手順2で作成したサンプルコード(ZIP)を選択します。
Lambda 関数が正常に更新されたことを確認します。
テスト
「テスト」タブを選択します。
「テスト」を選択します。
API Gateway に設定した固定値が取得できました。
{ "statusCode": 200, "message": "Hello, world!" }
なお、リクエストに認証情報がない場合はMissing Authentication Token
が返却されます。
{ "message": "Missing Authentication Token" }
認証情報はあるが権限が足りない場合は、次のような値となります。
{ "Message": "User: arn:aws:sts::123456789012:assumed-role/hato-client-lambda-role-kopdzhfl/hato-client-lambda is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:********9012:abcdef123/dev/GET/" }
最後に
この記事が誰かのお役にたてば幸いです。
参考資料
- API Gateway REST API の IAM 認証を有効にする
- IAM 認証の使用 - Amazon API Gateway
- Amazon Elasticsearch Service の使用開始: AWS SigV4 による署名付きリクエストを簡単に送信する方法 | Amazon Web Services ブログ
- [Python] Boto3以外でV4署名リクエストを行う | DevelopersIO
- API GatewayでAPIにIAM認証をかけて、Node.jsでSigV4署名ヘッダを作成してリクエストしてみる | DevelopersIO
- Zero Trust architecture for service-to-service workloads
- AWS API リクエスト署名の要素 - AWS 全般のリファレンス
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。